﻿using System;
using System.Threading.Tasks;
using SDCloudSolution.SDCloud.BusinessLayer.ModelData.Interfaces;
using SDCloudSolution.SDCloud.DataLayer.ModelData.Interfaces;
using SDCloudSolution.SDCloud.Entities.Models.Data;

namespace SDCloudSolution.SDCloud.BusinessLayer.ModelData
{
    public class ModelExecutionResultComponent : IModelExecutionResultComponent
    {
        private readonly IModelExecutionResultDataProvider _executionResultDataProvider;

        public ModelExecutionResultComponent(
                IModelExecutionResultDataProvider executionResultDataProvider
            )
        {
            _executionResultDataProvider = executionResultDataProvider;
        }

        public Task<ModelResultDataEntity> GetResultsDataByModelExecutionId(int modelExecutionId)
        {
            if (modelExecutionId <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(modelExecutionId), "Index should be greater than zero.");
            }

            return _executionResultDataProvider.GetResultsDataByModelExecutionIdAsync(modelExecutionId);
        }

        public Task<ModelResultDataEntity> GetResultsDataByModelExecutionIdAsync(int modelExecutionId, int framesSkipCount, int framesLimitCount)
        {
            if (modelExecutionId <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(modelExecutionId), "Index should be greater than zero.");
            }

            if (framesSkipCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(framesSkipCount), "Skip count can't be less than zero.");
            }

            if (framesLimitCount <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(framesLimitCount), "Limit count should be greater than zero.");
            }

            return _executionResultDataProvider.GetResultsDataByModelExecutionIdAsync(modelExecutionId, framesSkipCount, framesLimitCount);
        }

        public Task<ModelResultDataEntity> GetResultsDataByModelExecutionIdWithTimeFilter(int modelExecutionId, double? timeStart, double? timeEnd)
        {
            if (modelExecutionId <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(modelExecutionId), "Index should be greater than zero.");
            }

            if (!timeStart.HasValue && !timeEnd.HasValue)
            {
                throw new ArgumentException("Range is not specified.");
            }

            if (timeEnd.HasValue && timeStart.HasValue && timeStart.Value > timeEnd.Value)
            {
                throw new ArgumentOutOfRangeException(nameof(timeStart), "Time start should be less than Time end.");
            }

            return _executionResultDataProvider.GetResultsDataByModelExecutionIdWithTimeFilter(modelExecutionId, timeStart, timeEnd);
        }

        public Task InsertExecutionResutls(ModelResultDataEntity entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            return _executionResultDataProvider.InsertAsync(entity);
        }
    }
}
